//
//  MPCButton.m
//  Pods
//
//  Created by 蔡勋 on 2017/7/15.
//
//

#import "MPCButton.h"
#import "MPCButton+SDWebImage.h"
#import "MPCButton+YYWebImage.h"
#import <pthread.h>
#import "NSString+Tools.h"
#import "NSURL+Tools.h"
#import "objc/runtime.h"

#define MPWebImageFadeAnimationKey @"MPWebImageFadeAnimationKey"

@interface MPCButton ()


@end


@implementation MPCButton


#pragma mark - *********************************** View Lifecycle **********************************

/*!
 *  @author caixun
 *  @brief  只重写此方法，经过测试，调用init方法时会自动调用initWithFrame方法
 *  @param frame btn的frame
 *  @return 返回创建好的btn对象
 */
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        // 设置公共属性，与APP的UI规范 无关
        [self setCommonAttribute];
        [self initVariable];
    }
    
    return self;
}

/*!
 *  @author caixun
 *  @brief  设置公共属性，与APP的UI规范 无关
 */
- (void)setCommonAttribute
{
    if (self)
    {
        self.backgroundColor = [UIColor clearColor];
        
        self.opaque = YES;
        
        // 禁止多个Button同时响应点击事件
        self.exclusiveTouch = YES;
        
        // 在某些设备上可能会出现像素点显示不均匀的情况，设置该属性将超出bounds范围的剪切掉
        self.clipsToBounds = YES;
    }
}

/*!
 *  @author caixun
 *  @brief  初始化变量
 */
- (void)initVariable
{
    /// 默认显示占位图
    _isShowPlaceholderImg = YES;
    
    /// 默认时间为0.5秒
    _fltAnimDuration = 0.2;
    
    /// 默认是图片显示到image上
    _isSetBgImg = YES;
    _isShowDismissAnimated = YES;
}

- (void)dealloc
{
    
}

#pragma mark - ********************************** 初始化方法 工厂方法 *********************************

/*!
 *  @author caixun
 *  @brief  初始化基本设置
 *  @param frame 按钮的frame
 *  @return 返回创建好的按钮对象
 */
+ (instancetype)getWithFrame:(CGRect)frame
{
    MPCButton *btn = [[self alloc] initWithFrame:frame];
    
    return btn;
}

/*!
 *  @author caixun
 *  @brief  初始化按钮
 *  @param frame  按钮的frame
 *  @param target 按钮事件响应对象
 *  @param action 按钮事件的触发函数
 *  @return 返回创建好的按钮
 */
+ (instancetype)getWithFrame:(CGRect)frame target:(id)target action:(SEL)action
{
    MPCButton *btn = [[self alloc] initWithFrame:frame];
    
    /// 设置响应事件
    [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    
    return btn;
}


#pragma mark - ********************************** 初始化方法 实例方法 *********************************

/*!
 *  @author caixun
 *  @brief  初始化基本设置
 *  @param frame  按钮的frame
 *  @param target 响应按钮点击事件的对象
 *  @param action 按钮事件的触发函数
 *  @return 返回创建好的按钮
 */
- (instancetype)initWithFrame:(CGRect)frame target:(id)target action:(SEL)action
{
    if (self = [self initWithFrame:frame])
    {
        /// 设置响应事件
        [self addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    }
    
    return self;
}


#pragma mark - *********************************** 设置属性 实例方法 **********************************


/*!
 *  @author caixun
 *  @brief  设置target和action
 *  @param target 响应按钮点击事件的对象
 *  @param action 按钮事件的触发函数
 */
- (void)setTarget:(id)target action:(SEL)action
{
    if (self)
    {
        [self addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    }
}

/*!
 *  @author caixun
 *  @brief  设置Image
 *  @param imgNor 默认状态下按钮的图片
 */
- (void)setNorImg:(UIImage *)imgNor
{
    if (self)
    {
        [self setImage:imgNor forState:UIControlStateNormal];
    }
}

/*!
 *  @author caixun
 *  @brief  设置BgImage
 *  @param imgBgNor 默认状态下按钮的背景图片
 */
- (void)setNorBgImg:(UIImage *)imgBgNor
{
    if (self)
    {
        [self setBackgroundImage:imgBgNor forState:UIControlStateNormal];
    }
}

/*!
 *  @author caixun
 *  @brief  同时设置BgImage和Title
 *  @param imgBgNor      默认状态下按钮的背景图片
 *  @param strNorTitle   默认状态下按钮的文字
 *  @param colorNorTitle 默认状态下按钮的文字颜色
 *  @param fontTitle     默认状态下按钮的字体
 */
- (void)setNorBgImg:(UIImage *)imgBgNor
           norTitle:(NSString *)strNorTitle
      norTitleColor:(UIColor *)colorNorTitle
          titleFont:(UIFont *)fontTitle
{
    if (self)
    {
        [self setBackgroundImage:imgBgNor forState:UIControlStateNormal];
        [self setTitle:strNorTitle forState:UIControlStateNormal];
        [self setTitleColor:colorNorTitle forState:UIControlStateNormal];
        self.titleLabel.font = fontTitle;
    }
}

/*!
 *  @author caixun
 *  @brief  设置圆角，边框
 *  @param fltCornerRadius 圆角的角度
 *  @param fltBorderWidth  边框宽度
 *  @param colorBorder     边框的颜色
 */
- (void)setCornerRadius:(CGFloat)fltCornerRadius
            borderWidth:(CGFloat)fltBorderWidth
            borderColor:(UIColor *)colorBorder
{
    if (self)
    {
        self.layer.cornerRadius = fltCornerRadius;
        self.layer.borderColor = colorBorder.CGColor;
        
        /// 根据屏幕的分辨率倍数适配边框宽度
        self.layer.borderWidth = fltBorderWidth;
    }
}

- (void)setCornerRadiusForAll:(float)cornerRadius
{
    self.clipsToBounds = YES;
    self.layer.cornerRadius = cornerRadius;
}

- (void)setCornerRadiusForPart:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii
{
    // 上面两个圆角
    UIBezierPath *maskPath=  [UIBezierPath bezierPathWithRoundedRect:self.bounds
                                                   byRoundingCorners:corners
                                                         cornerRadii:cornerRadii];
    
    CAShapeLayer *maskLayer=[[CAShapeLayer alloc] init];
    
    maskLayer.frame=self.bounds;
    
    maskLayer.path=maskPath.CGPath;
    
    self.layer.mask=maskLayer;
    
    self.layer.masksToBounds=YES;
}

- (MPCButton * _Nullable (^_Nullable)(BOOL))setBgImg
{
    return ^MPCButton *(BOOL setBgImg)
    {
        _isSetBgImg = setBgImg;
        
        return self;
    };
}

- (MPCButton * _Nullable (^_Nullable)(BOOL))showDismissAnimated
{
    return ^MPCButton *(BOOL showDismissAnimated)
    {
        _isShowDismissAnimated = showDismissAnimated;
        
        return self;
    };
}

- (MPCButton * _Nullable (^_Nullable)(CGFloat))animDuration
{
    return ^MPCButton *(CGFloat animDuration)
    {
        _fltAnimDuration = animDuration;
        
        return self;
    };
}

- (MPCButton * _Nullable (^_Nullable)(UIImage *_Nullable))imagePlaceholder
{
    return ^MPCButton *(UIImage *imagePlaceholder)
    {
        _imgPlaceholder = imagePlaceholder;
        
        return self;
    };
}

- (MPCButton * _Nullable (^_Nullable)(UIImage *_Nullable))imageError
{
    return ^MPCButton *(UIImage *imageError)
    {
        _imgError = imageError;
        
        return self;
    };
}

- (MPCButton * _Nullable (^_Nullable)(BOOL))showPlaceholderImg
{
    return ^MPCButton *(BOOL showPlaceholderImg)
    {
        _isShowPlaceholderImg = showPlaceholderImg;
        
        return self;
    };
}


#pragma mark -- 网络加载URL图片

/**
 网络图片加载的方法
 
 */
- (void)mp_setImageWithURL:(nullable NSString *)imageStrURL
{
    [self mp_setImageWithURL:imageStrURL options:0 progress:nil success:nil fail:nil];
}

- (void)mp_setImageWithURL:(nullable NSString *)imageStrURL options:(MPWebImageOptions)options
{
    [self mp_setImageWithURL:imageStrURL options:options progress:nil success:nil fail:nil];
}

- (void)mp_setImageWithURL:(nullable NSString *)imageStrURL
                   options:(MPWebImageOptions)options
                   success:(nullable MPWebImageSuccessBlock)success
                      fail:(nullable MPWebImageFailBlock)fail
{
    [self mp_setImageWithURL:imageStrURL options:options progress:nil success:success fail:fail];
}


- (void)mp_setImageWithURL:(nullable NSString *)imageStrURL
                   options:(MPWebImageOptions)options
                  progress:(nullable MPWebImageDownloaderProgressBlock)progressBlock
                   success:(nullable MPWebImageSuccessBlock)success
                      fail:(nullable MPWebImageFailBlock)fail
{
    /// 检查URL是否合理
    NSURL *imageURL = [self changeImageUrl:imageStrURL];
    if (MPT_URL_Not_Valid(imageURL))
    {
        return;
    }
    
    /// 移除之前下载队列
    [self mp_cancelCurrentImageLoadWithURL:imageURL];
    [self.layer removeAnimationForKey:MPWebImageFadeAnimationKey];
    
    /// 设置默认图片  如果用户没有设置自动填充图片模式
    [self mp_setPlaceholderWithOptions:options];

    /// 读取缓存中的图片
    UIImage *imageMemory = [self mp_getCatcheMemoryImageWithImageURL:imageURL options:options];
    
    if (imageMemory)
    {
        if (success)
        {
            success(imageMemory,imageURL,MPWebImageFromType_Memory,MPWebImageStage_Finished);
        }
        
        return;
    }
    
    /// 读取硬盘中的图片
    [self mp_getCatcheDiskImageWithImageURL:imageURL options:options finish:^(UIImage *image)
     {
         /// 硬盘中有图片
         if (image)
         {
             if (success)
             {
                 success(image,imageURL,MPWebImageFromType_Disk,MPWebImageStage_Finished);
             }
         }
         /// 硬盘中无图片，需要下载
         else
         {
             /// 下载网络图片
             [self mp_downImageWithImageURL:imageURL options:options progress:progressBlock success:success fail:fail];
         }
         
     }];
}

/// 是否显示图片（有图模式）
- (BOOL)shouldShowImage
{
    // 先写死，日后如果有需求的话弄个成员变量去控制
    return YES;
}

- (BOOL)tpCheckImageURL:(NSString *)strImgUrl
{
    if (!([strImgUrl hasPrefix:@"http:"] || [strImgUrl hasPrefix:@"https:"])) /// 不是URL,直接返回NO
    {
        return NO;
    }
    
    /// 对URL转码，处理URL中有汉字的情况
    NSString *strCode = [strImgUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    /// 获取img的URL
    NSURL *urlImg = [NSURL URLWithString:strCode];
    
    /// 根据urlImg的path是否为空来判断是否为图片地址
    return MPT_Str_Is_Valid([urlImg path]);
}

- (NSURL *)changeImageUrl:(NSString *)strImgUrl
{
    /// 无图片模式，直接返回
    if (![self shouldShowImage])
    {
        return nil;
    }
    
    /// 图片连接是为空，直接返回
    if (MPT_Str_Not_Valid(strImgUrl))
    {
        return nil;
    }
    
    /// 图片链接是否正常
    if (![self tpCheckImageURL:strImgUrl])
    {
        return nil;
    }
    
    /// 对URL转码，处理URL中有汉字的情况
    strImgUrl = [strImgUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    /// 获取img的URL
    NSURL *urlImg = [NSURL URLWithString:strImgUrl];
    
    return urlImg;
}

/// 淡入动画，从无到有
- (void)animationEaseIn:(UIView *)view
{
    CATransition *transition = [CATransition animation];
    transition.duration = 0.2;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionFade;
    [self.layer addAnimation:transition forKey:MPWebImageFadeAnimationKey];
}

- (void)noFinishWhitImage:(UIImage *)image
{
    [self setImageWithImage:image];
}

- (void)didFinishWithImage:(UIImage*)image
{
    /// 加入一个保护，判断是否下载完成成功
    if ((![image isKindOfClass:[UIImage class]])
        || (image.size.height <= 0))
    {
        return;
    }
    
    /// 下载图片成功，显示图片
    [self setImageWithImage:image];
    /// 下载成功后，设置显示模式，此时使用的是调用commonContentMode:方法设置的值，在外面手动调用系统方法是不起作用的
    
    ///  是否显示消失动画
    if (self.isShowDismissAnimated)
    {
        [self animationEaseIn:self];
    }
}

- (void)didFailWithError:(NSError *)error
{
#ifdef DEBUG /// 测试模式下
    if (error.code == 404) /// 如果是404则显示提示404错误图片
    {
        
    }
#endif
    
    if (!_imgError || ![_imgError isKindOfClass:[UIImage class]])
    {
        [self setImageWithImage:self.imgPlaceholder];
        
        return;
    }
    
    /// 设置错误图片
    [self setImageWithImage:_imgError];

    
    ///  是否显示消失动画
    if (self.isShowDismissAnimated)
    {
        [self animationEaseIn:self];
    }
    
}

- (void)setImageWithImage:(UIImage *)img
{
    if (self.isSetBgImg) /// 判断是设置成背景图片还是普通图片
    {
        [self setBackgroundImage:img forState:UIControlStateNormal];
    }
    else
    {
        [self setImage:img forState:UIControlStateNormal];
    }
}


#pragma mark -- 需要区分SDK的部分

+ (dispatch_queue_t)mp_setterQueue
{
    static dispatch_queue_t queue;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        queue = dispatch_queue_create("com.yixia.mpwebimage.setter", DISPATCH_QUEUE_SERIAL);
        dispatch_set_target_queue(queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
    });
    return queue;
}

- (void)mp_cancelCurrentImageLoadWithURL:(NSURL *)url
{
#if MPT_USE_SDWebImageSwitch
    
    [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"];
#else
    [self yy_cancelCurrentImageLoadWithURL:url];
    
#endif
    
}



- (void)mp_setPlaceholderWithOptions:(MPWebImageOptions)options
{
    mp_dispatch_main_sync_safe(^{
        
        if (options & MPWebImageOption_IgnorePlaceHolder)
        {
            return;
        }
        
        /// 下载之前显示占位图片
        if (_isShowPlaceholderImg)
        {
            [self setImageWithImage:_imgPlaceholder];
        }
        
    });
}

- (UIImage *)mp_getCatcheMemoryImageWithImageURL:(NSURL *)imgUrl options:(MPWebImageOptions)options
{
#if MPT_USE_SDWebImageSwitch
    return [self sd_getCatcheMemoryImageWithImageURL:imgUrl options:options];
    
#else
    
    return [self yy_getCatcheMemoryImageWithImageURL:imgUrl options:options];
    
#endif
    
}

- (void)mp_getCatcheDiskImageWithImageURL:(NSURL *)imgUrl options:(MPWebImageOptions)options finish:(void (^)(UIImage *image))finish
{
#if MPT_USE_SDWebImageSwitch
    
    [self sd_getCatcheDiskImageWithImageURL:imgUrl options:options finish:finish];
#else
    [self yy_getCatcheDiskImageWithImageURL:imgUrl options:options finish:finish];
    
#endif
    
}

- (void)mp_downImageWithImageURL:(NSURL *)imgUrl
                         options:(MPWebImageOptions)options
                        progress:(MPWebImageDownloaderProgressBlock)progressBlock
                         success:(nullable MPWebImageSuccessBlock)success
                            fail:(nullable MPWebImageFailBlock)fail
{
    
#if MPT_USE_SDWebImageSwitch
    
    [self sd_downImageWithImageURL:imgUrl
                           options:options
                          progress:progressBlock
                           success:success
                              fail:fail];
#else
    [self yy_downImageWithImageURL:imgUrl
                           options:options
                          progress:progressBlock
                           success:success
                              fail:fail];
#endif
    
}


@end
